package com.ruoyi.framework.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.util.Utils;
import com.ruoyi.framework.aspectj.lang.enums.DataSourceType;
import com.ruoyi.framework.config.properties.DruidProperties;
import com.ruoyi.framework.datasource.DynamicDataSource;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.servlet.*;
import javax.sql.DataSource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * druid 配置多数据源
 *
 * @author ruoyi
 */
@Configuration
public class DruidConfig {
    @Bean
    @ConfigurationProperties("spring.datasource.druid.master")
    public DataSource masterDataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.slave")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
    public DataSource slaveDataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.account")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.account", name = "enabled", havingValue = "true")
    public DataSource accountDataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.payment")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.payment", name = "enabled", havingValue = "true")
    public DataSource paymentDataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.poem")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.poem", name = "enabled", havingValue = "true")
    public DataSource poemDataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.dict")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.dict", name = "enabled", havingValue = "true")
    public DataSource dictDataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.game")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.game", name = "enabled", havingValue = "true")
    public DataSource gameDataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.storage")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.storage", name = "enabled", havingValue = "true")
    public DataSource storageDataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.yuwen")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.yuwen", name = "enabled", havingValue = "true")
    public DataSource yuwenDataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.kkcuser")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.kkcuser", name = "enabled", havingValue = "true")
    public DataSource kkcuserDataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.kkcuser3")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.kkcuser3", name = "enabled", havingValue = "true")
    public DataSource kkcuser3DataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.kkad")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.kkad", name = "enabled", havingValue = "true")
    public DataSource kkadDataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.kkwenyanwen")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.kkwenyanwen", name = "enabled", havingValue = "true")
    public DataSource kkwenyanwenDataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.kkformula")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.kkformula", name = "enabled", havingValue = "true")
    public DataSource kkformulaDataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.kkpoembbs")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.kkpoembbs", name = "enabled", havingValue = "true")
    public DataSource kkpoembbsDataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }


    @Bean(name = "dynamicDataSource")
    @Primary
    public DynamicDataSource dataSource(DataSource masterDataSource, DataSource slaveDataSource, DataSource accountDataSource, DataSource paymentDataSource, DataSource poemDataSource, DataSource dictDataSource, DataSource gameDataSource, DataSource storageDataSource, DataSource yuwenDataSource, DataSource kkcuserDataSource, DataSource kkcuser3DataSource, DataSource kkadDataSource, DataSource kkwenyanwenDataSource, DataSource kkformulaDataSource, DataSource kkpoembbsDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
        targetDataSources.put(DataSourceType.SLAVE.name(), slaveDataSource);
        targetDataSources.put(DataSourceType.ACCOUNT.name(), accountDataSource);
        targetDataSources.put(DataSourceType.PAYMENT.name(), paymentDataSource);
        targetDataSources.put(DataSourceType.POEM.name(), poemDataSource);
        targetDataSources.put(DataSourceType.DICT.name(), dictDataSource);
        targetDataSources.put(DataSourceType.GAME.name(), gameDataSource);
        targetDataSources.put(DataSourceType.STORAGE.name(), storageDataSource);
        targetDataSources.put(DataSourceType.YUWEN.name(), yuwenDataSource);
        targetDataSources.put(DataSourceType.KKCUSER.name(), kkcuserDataSource);
        targetDataSources.put(DataSourceType.KKCUSER3.name(), kkcuser3DataSource);
        targetDataSources.put(DataSourceType.KKAD.name(), kkadDataSource);
        targetDataSources.put(DataSourceType.KKWENYANWEN.name(), kkwenyanwenDataSource);
        targetDataSources.put(DataSourceType.KKFORMULA.name(), kkformulaDataSource);
        targetDataSources.put(DataSourceType.POEMBBS.name(), kkpoembbsDataSource);
        return new DynamicDataSource(masterDataSource, targetDataSources);
    }

    /**
     * 去除监控页面底部的广告
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    @Bean
    @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) {
        // 获取web监控页面的参数
        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
        // 提取common.js的配置路径
        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
        final String filePath = "support/http/resources/js/common.js";
        // 创建filter进行过滤
        Filter filter = new Filter() {
            @Override
            public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
            }

            @Override
            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
                chain.doFilter(request, response);
                // 重置缓冲区，响应头不会被重置
                response.resetBuffer();
                // 获取common.js
                String text = Utils.readFromResource(filePath);
                // 正则替换banner, 除去底部的广告信息
                text = text.replaceAll("<a.*?banner\"></a><br/>", "");
                text = text.replaceAll("powered.*?shrek.wang</a>", "");
                response.getWriter().write(text);
            }

            @Override
            public void destroy() {
            }
        };
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(filter);
        registrationBean.addUrlPatterns(commonJsPattern);
        return registrationBean;
    }
}
